﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace WaitHandle
{
    class Program
    {
        private delegate int TakesAWhileDelegate(int x, int ms);

        static void Main(string[] args)
        {
            SemaPhoreExample();
            Console.ReadLine();
        }

        private static void WaitHandleExample()
        {
            TakesAWhileDelegate dl = TakesAWhile;


            IAsyncResult ar = dl.BeginInvoke(1, 3000, x =>
            {
                Console.WriteLine("End Function");
            }, null);
            while (true)
            {
                Console.Write(".");
                if (ar.AsyncWaitHandle.WaitOne(50))
                {
                    Console.WriteLine("Can get the result now");
                    break;
                }
            }

            int result = dl.EndInvoke(ar);
            Console.WriteLine($"result:{result}");
        }

        private static void SemaPhoreExample()
        {
            int taskCount = 6;
            int semaphoreCount = 3;
            var semaphore = new SemaphoreSlim(semaphoreCount, semaphoreCount);//控制最大线程并发量
            var tasks = new Task[taskCount];
            for (int i = 0; i < taskCount; i++)
            {
                tasks[i] = Task.Run(() => TaskSemaPhore(semaphore));
            }

            Task.WaitAll(tasks);
            Console.WriteLine("All tasks finished");
        }
        public static int TakesAWhile(int x, int ms)
        {
            Task.Delay(ms).Wait();
            Console.WriteLine("return is 42");
            return 42;
        }

        public static void TaskSemaPhore(SemaphoreSlim semaphore)
        {
            bool isCompleted = false;
            while (!isCompleted)
            {
                if (semaphore.Wait(600))
                {
                    try
                    {
                        Console.WriteLine($"Task{Task.CurrentId} locks the semaphore");
                        Task.Delay(2000).Wait();
                    }
                    
                    finally
                    {
                        Console.WriteLine($"Task{Task.CurrentId} releases the semaphore");
                        semaphore.Release();
                        isCompleted = true;
                    }
                }
                else
                {
                    Console.WriteLine($"Timeout for task{Task.CurrentId}; wait again");
                }
            }
        }
    }
}
